package com.acheli.rideable.functionLathes.component.engine;


import com.acheli.registry.config.settings.EngineMode;
import com.acheli.registry.network.ACHeliPacketType;
import com.acheli.rideable.entites.RideableEntity;

import com.acheli.rideable.functionLathes.ComponentFL;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.phys.Vec3;


import java.util.Objects;

public class EngineFL extends ComponentFL implements AbstractEngine{
    RideableEntity masterRideable;
    public String ID = "";
    private double power = 0F;
    private double revolutionSpeed = 0F;
    private double maximumRevSpeed = 0F;
    private double readyRevSpeed = 0F;
    private double revDeltaPerTick = 0F;
    private final double defaultRevDeltaPerTick;
    private int engineTimeout = 0;
    private int engineTimeoutThreshold = 0;
    private int engineTimeoutCooldown = 0;
    private boolean engineStatus = false;
    private boolean isClosed = false;
    private boolean isReady = false;
    private boolean isMaxed = false;

    private EngineMode engineMode = EngineMode.Simulation;

    EngineFL(String ID, RideableEntity masterRideable, Vec3 relativePosition, double maximumRevSpeed, double readyRevSpeed, int engineTimeoutCooldown, int engineTimeoutThreshold, double revDeltaPerTick){
        super(ID, masterRideable, relativePosition);
        this.ID = ID;
        setMaximumRevSpeed(maximumRevSpeed);
        setReadyRevSpeed(readyRevSpeed);
        setEngineTimeoutCooldown(engineTimeoutCooldown);
        setEngineTimeoutThreshold(engineTimeoutThreshold);
        defaultRevDeltaPerTick = revDeltaPerTick;
        setRevDeltaPerTick(revDeltaPerTick);
    }



    @Override
    public CompoundTag clientSending(ACHeliPacketType packetType) {
        CompoundTag nbt = super.clientSending(packetType);
        if (Objects.requireNonNull(packetType) == ACHeliPacketType.ComponentActive) {
            nbt.putString("engineMode", engineMode.name());
        }

        return nbt;
    }

    @Override
    public CompoundTag serverReceiveAndSending(CompoundTag serverOriginNbt, ServerPlayer executingPlayer, ACHeliPacketType packetType) {
        if (Objects.requireNonNull(packetType) == ACHeliPacketType.ComponentActive) {
            engineMode = EngineMode.valueOf(serverOriginNbt.getString("engineMode"));
        }
        return super.serverReceiveAndSending(serverOriginNbt, executingPlayer, packetType);
    }

    public void setMode(EngineMode engineMode) {
        this.engineMode = engineMode;
    }

    @Override
    public void setRevolutionSpeed(double revolutionSpeed) {
        if (revolutionSpeed > 0) {
            double max = getMaximumRevSpeed();
            this.revolutionSpeed = Math.min(revolutionSpeed, max);
        } else if (revolutionSpeed <= 0){
            this.revolutionSpeed = 0;
        }
    }

    @Override
    public double getRevolutionSpeed() {
        return this.revolutionSpeed;
    }

    @Override
    public void setReadyRevSpeed(double readyRevSpeed) {
        this.readyRevSpeed = readyRevSpeed;
    }

    @Override
    public double getReadyRevSpeed() {
        return this.readyRevSpeed;
    }

    @Override
    public void setMaximumRevSpeed(double maximumRevSpeed) {
        this.maximumRevSpeed = maximumRevSpeed;
    }

    @Override
    public double getMaximumRevSpeed() {
        return this.maximumRevSpeed;
    }

    @Override
    public void setRevDeltaPerTick(double revDeltaPerTick) {
        this.revDeltaPerTick = revDeltaPerTick;
    }

    @Override
    public double getRevDeltaPerTick() {
        return this.revDeltaPerTick;
    }

    @Override
    public void setEngineTimeout(int engineTimeout) {
        this.engineTimeout = engineTimeout;
    }

    @Override
    public int getEngineTimeout() {
        return this.engineTimeout;
    }

    @Override
    public void setEngineTimeoutThreshold(int engineTimeoutThreshold) {
        this.engineTimeoutThreshold = engineTimeoutThreshold;
    }

    @Override
    public int getEngineTimeoutThreshold() {
        return this.engineTimeoutThreshold;
    }

    @Override
    public void setEngineTimeoutCooldown(int engineTimeoutCooldown) {
        this.engineTimeoutCooldown = engineTimeoutCooldown;
    }

    @Override
    public int getEngineTimeoutCooldown() {
        return this.engineTimeoutCooldown;
    }


    public void setPower(double powerValue) {
        this.power = powerValue;
    }


    public double getPower() {
        return this.power;
    }


    @Override
    public void tick() {
        super.tick();
        switch (engineMode) {

            case Convenient -> {
                setRevDeltaPerTick(getMaximumRevSpeed());
            }

            case Simulation -> {
                setRevDeltaPerTick(defaultRevDeltaPerTick);
            }
            default -> {}
        }

        int _timeout = engineTimeout;
        int _cooldown = engineTimeoutCooldown;
        //发动机按键时长检测
        if (_timeout > getEngineTimeoutThreshold()){//阈值设置
            _timeout = -_cooldown;//CD设置
            engineStatusChanging();//状态改变

        } else if (_timeout  < 0){//CD恢复
            _timeout += 1;
        }
        setEngineTimeout(_timeout);


        //发动机转速逻辑
        double delta;
        double maxRevSpeed = getMaximumRevSpeed();
        double readyRevSpeed = getReadyRevSpeed();
        if (engineStatus && getRevolutionSpeed() < maxRevSpeed) {
            delta = this.revDeltaPerTick;
            setRevolutionSpeed(getRevolutionSpeed()  + delta );

        } else if (!engineStatus && getRevolutionSpeed() > 0){
            delta = -this.revDeltaPerTick;
            setRevolutionSpeed(getRevolutionSpeed()  + delta );
        }

        if (getRevolutionSpeed() <= 0){
            if (! this.isClosed){
                onEngineClosed();
                this.isClosed = true;
            }

        } else {
            this.isClosed = false;
        }

        if (engineStatus && getRevolutionSpeed() >= readyRevSpeed) {
            if (! this.isReady){
                onEngineIsReady();
                this.isReady = true;
            }

        } else {
            this.isReady = false;
        }

        if (engineStatus && getRevolutionSpeed() >= maxRevSpeed) {
            if (! this.isMaxed){
                onEngineMaxed();
                this.isMaxed = true;
            }
        } else {
            this.isMaxed = false;
        }


    }


    @Override
    public void engineSwitch() {
        setEngineTimeout(getEngineTimeout() + 1);
    }

    @Override
    public void engineRunning() {
        engineStatus = true;
    }

    @Override
    public void onEngineIsReady() {
    }

    @Override
    public void onEngineMaxed() {
    }

    @Override
    public void engineStopping() {engineStatus = false;}

    @Override
    public void onEngineClosed() {

    }

    @Override
    public void setEngineStatus(boolean engineStatus) {
        this.engineStatus = engineStatus;
    }

    @Override
    public boolean getEngineStatus() {
        return this.engineStatus;
    }

    @Override
    public void engineStatusChanging() {
        if (this.engineStatus) {
            engineStopping();
        } else {
            engineRunning();
        }
    }

}
